package com.njcb.ams.web.advice;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.njcb.ams.pojo.bo.Head;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.njcb.ams.pojo.dto.standard.EntityResponse;
import com.njcb.ams.pojo.dto.standard.PageResponse;
import com.njcb.ams.portal.SysBaseDefine;
import com.njcb.ams.factory.comm.DataBus;
import com.njcb.ams.service.ExportService;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.support.springmvc.converter.AmsMappingJackson2HttpMessageConverter;
import com.njcb.ams.util.AmsDateUtils;
import com.njcb.ams.util.AmsJsonUtils;

/**
 * mvc返回适配，统一处理Excel导出功能
 * 
 * @author liuyanlong
 *
 */
@Order(2)
@ControllerAdvice
public class ExportResponseBodyAdvice implements ResponseBodyAdvice<Object> {
	private static final Logger logger = LoggerFactory.getLogger(ExportResponseBodyAdvice.class);

	@Override
	@SuppressWarnings("unchecked")
	public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType contentType, Class<? extends HttpMessageConverter<?>> converterType, ServerHttpRequest request,
			ServerHttpResponse response) {
		if (request instanceof ServletServerHttpRequest && (body instanceof Map || body instanceof PageResponse)) {
			ServletServerHttpRequest sshreq = (ServletServerHttpRequest) request;
			Head requestHead = DataBus.getObject(Head.class);
			String model = SysBaseDefine.QUERY_MODEL_NORMAL;
			if(null != requestHead){
				model = requestHead.getModel();
			}
			try {
				Map<String, Object> modelMap = null;
				List<Object> colData = null;
				//生成Excel时需要的字典码值
				Map<String, Map<String, String>> excelDicMap = new HashMap<String, Map<String, String>>();
				if (SysBaseDefine.QUERY_MODEL_EXPALL.equals(model)) {
					//生成excel
					if (body instanceof Map) {
						Map<String, Object> modelMapBody = (Map<String, Object>) body;
						modelMap = (Map<String, Object>)modelMapBody.get("extValues");
						colData = (List<Object>) ((Map<?, ?>) body).get("rows");
					}else if(body instanceof PageResponse){
						PageResponse<?> modelMapBody = (PageResponse<?>) body;
						modelMap = (Map<String, Object>)modelMapBody.getExtValues();
						colData = (List<Object>) modelMapBody.getRows();
					} else {
						ExceptionUtil.throwAppException("导出功能只允许返回MAP或Response类型数据");
					}
					
					if(null == modelMap || null == colData){
						return body;
					}
					
					Map<String, Map<String, String>> dataDicMap = (Map<String, Map<String, String>>) modelMap.get(SysBaseDefine.REQ_PARAM_DICMAP);
					Map<String, List<String>> ret = requestHead.getDataDic();
					if (null != ret) {
						for (String key : ret.keySet()) {
							List<String> rtList = ret.get(key);
							for (String string : rtList) {
								excelDicMap.put(string, dataDicMap.get(key));
							}
						}
					}
					Object colTitle = requestHead.getColumnTitle();
					List<String> titleNameArray = null;
					if(colTitle instanceof ArrayList){
						titleNameArray = (List<String>)colTitle;
					}else{
						titleNameArray = AmsJsonUtils.toArrayList(((String)colTitle).replaceAll("'", "\""));
					}
					Object colValue = requestHead.getColumnValue();
					List<String> titleValueArray = null;
					if(colValue instanceof ArrayList){
						titleValueArray = (List<String>)colValue;
					}else{
						titleValueArray = AmsJsonUtils.toArrayList(((String)colValue).replaceAll("'", "\""));
					}
					String fileName = sshreq.getServletRequest().getParameter("fileName");
					fileName = StringUtils.isEmpty(fileName) ? "" : fileName;
					fileName = fileName + AmsDateUtils.getCurrentDate8() + AmsDateUtils.getCurrentTime6() + ".xlsx";
					ServletServerHttpResponse sshrsp = (ServletServerHttpResponse) response;
					sshrsp.getServletResponse().setCharacterEncoding("UTF-8");
					sshrsp.getServletResponse().setContentType("multipart/form-data");
					sshrsp.getServletResponse().setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes(),"ISO8859-1"));
					sshrsp.getServletResponse().setContentType("application/json;charset=utf-8");
					PrintWriter out = sshrsp.getServletResponse().getWriter();

					AmsMappingJackson2HttpMessageConverter.CONVERTER_PARAM = AmsMappingJackson2HttpMessageConverter.PARAM_TYPE_02;

					File homeFile = new File(SysBaseDefine.SYS_FILE_TMP_PATH);
					if(!homeFile.exists() || !homeFile.isDirectory()){
						homeFile.mkdir();
					}
					
					File excelFile = new File(SysBaseDefine.SYS_FILE_TMP_PATH+fileName);
					if(!excelFile.exists()){
						excelFile.createNewFile();
					}
					FileOutputStream fos = new FileOutputStream(excelFile);
					ExportService.getInstance().exportData(titleNameArray, titleValueArray, colData, excelDicMap, fos);
					out.write(AmsJsonUtils.objectToJson(EntityResponse.build(excelFile.getPath())));
					out.flush();
					out.close();
				}
			} catch (Exception e) {
				logger.error("\n导出Excel功能出错");
				ExceptionUtil.printStackTrace(e);
				ExceptionUtil.throwAppException(e);
			}
		}
		return body;
	}

	@Override
	public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
		// 判断Controller返回值是否Map，如果是则返回true执行此处理，否则不处理
		Class<?> rtClass = returnType.getMethod().getReturnType();
		if (rtClass.isAssignableFrom(Map.class) || PageResponse.class.isAssignableFrom(rtClass)) {
			return true;
		} else {
			return false;
		}
	}

}
